<template>
  <!-- 只渲染 el-switch -->
  <el-switch
    v-bind="$attrs"
    v-model="selectedValue"
    :active-value="switchActiveValueComputed"
    :inactive-value="switchInactiveValueComputed"
    :active-text="switchActiveTextComputed"
    :inactive-text="switchInactiveTextComputed"
    :disabled="isLoading"
    @change="handleChange"
  >
  </el-switch>
</template>

<script setup>
import { ref, watch, computed, nextTick } from 'vue';
import { useDictStore } from '@/store';
// 显式导入 ElSwitch
import { ElSwitch } from 'element-plus';

const props = defineProps({
  code: {
    type: String,
    required: true,
  },
  perms: {
    type: Boolean,
    default: false,
  },
  modelValue: {
    // For v-model support, el-switch 期望一个布尔值、字符串或数字
    type: [String, Number, Boolean],
    default: null, // 默认值改为 null，以便更好地推断初始类型
  },
  // el-switch 特有 props，用于自定义开关的值和文本
  switchActiveValue: {
    type: [String, Number, Boolean],
    default: 1, // 默认开启状态的值改为 1
  },
  switchInactiveValue: {
    type: [String, Number, Boolean],
    default: 0, // 默认关闭状态的值改为 0
  },
  switchActiveText: {
    type: String,
    default: '', // 默认开启状态的文本
  },
  switchInactiveText: {
    type: String,
    default: '', // 默认关闭状态的文本
  },
});

const emit = defineEmits(['update:modelValue', 'change']);

const dictStore = useDictStore();
const options = ref([]);
const isLoading = ref(false);
const dataLoaded = ref(false);

// 辅助函数：将任意值标准化为 1 (开启) 或 0 (关闭)
const normalizeToBinary = (val) => {
  if (typeof val === 'number') {
    return val !== 0 ? 1 : 0;
  }
  if (typeof val === 'string') {
    const num = Number(val);
    if (!isNaN(num)) {
      // 可以转换为数字的字符串
      return num !== 0 ? 1 : 0;
    } else {
      // 不能转换为数字的字符串
      return val !== '' ? 1 : 0; // 非空字符串为 1，空字符串为 0
    }
  }
  if (typeof val === 'boolean') {
    return val ? 1 : 0;
  }
  // 对于 null, undefined 或其他类型，默认视为关闭
  return 0;
};

// 计算属性：为 el-switch 提供 active-value，优先使用 props，其次字典数据，最后默认值
const switchActiveValueComputed = computed(() => {
  // 如果字典数据有第一个条目，则使用其 value
  if (options.value.length > 0) {
    return options.value[0].value;
  }
  // 否则，使用 props 中设置的 activeValue (默认是 1)
  return props.switchActiveValue;
});

// 计算属性：为 el-switch 提供 inactive-value，优先使用 props，其次字典数据，最后默认值
const switchInactiveValueComputed = computed(() => {
  // 如果字典数据有第二个条目，则使用其 value
  if (options.value.length > 1) {
    return options.value[1].value;
  }
  // 否则，使用 props 中设置的 inactiveValue (默认是 0)
  return props.switchInactiveValue;
});

// 计算属性：为 el-switch 提供 active-text，优先使用 props，其次字典数据，最后默认值 (此逻辑已关闭，如果需要请自行开启)
const switchActiveTextComputed = computed(() => {
  // if (props.switchActiveText !== '') {
  //   return props.switchActiveText;
  // }
  // return options.value.length > 0 ? options.value[0].label : '';
  return props.switchActiveText;
});

// 计算属性：为 el-switch 提供 inactive-text，优先使用 props，其次字典数据，最后默认值 (此逻辑已关闭，如果需要请自行开启)
const switchInactiveTextComputed = computed(() => {
  // if (props.switchInactiveText !== '') {
  //   return props.switchInactiveText;
  // }
  // return options.value.length > 1 ? options.value[1].label : '';
  return props.switchInactiveText;
});

// 计算属性：用于 el-switch 的 v-model 绑定
const selectedValue = computed({
  get() {
    const activeVal = switchActiveValueComputed.value;
    const inactiveVal = switchInactiveValueComputed.value;

    // 如果 modelValue 已经与 active/inactive 值严格相等，直接返回
    if (props.modelValue === activeVal) return activeVal;
    if (props.modelValue === inactiveVal) return inactiveVal;

    // 否则，根据业务规则将 modelValue 转换为 1 (开) 或 0 (关)
    const normalized = normalizeToBinary(props.modelValue);

    // 将标准化后的 1/0 映射回 el-switch 实际使用的 active/inactive 值
    return normalized === 1 ? activeVal : inactiveVal;
  },
  set(value) {
    // 'value' 是 el-switch 内部发出的 activeVal 或 inactiveVal (例如 1 或 0)
    let emittedValue = value;
    const originalModelValue = props.modelValue; // 获取原始 modelValue 以推断类型

    // 判断当前开关状态是“开”还是“关”
    const isOn = value === switchActiveValueComputed.value;

    // 尝试将值转换回原始 modelValue 的类型
    if (typeof originalModelValue === 'boolean') {
      emittedValue = isOn;
    } else if (typeof originalModelValue === 'number') {
      emittedValue = isOn
        ? Number(switchActiveValueComputed.value)
        : Number(switchInactiveValueComputed.value);
    } else if (typeof originalModelValue === 'string') {
      emittedValue = isOn
        ? String(switchActiveValueComputed.value)
        : String(switchInactiveValueComputed.value);
    }
    // 如果原始 modelValue 是 null/undefined 或其他类型，则直接发出 el-switch 传来的值

    emit('update:modelValue', emittedValue);
  },
});

const fetchDictionaryData = async () => {
  if (!props.code) return;

  isLoading.value = true;
  dataLoaded.value = false;

  try {
    const data = await dictStore.getDictionary(props.code, props.perms);
    options.value = data.map((item) => {
      const rawItemValue = item.value !== undefined ? item.value : item.id;
      let finalItemValue = rawItemValue;

      // 这里的类型转换是为了确保字典数据中的 value 与 el-switch 的 active/inactive-value 类型匹配
      // 默认情况下，active/inactive-value 是 1/0，所以尝试将字典值转换为数字或字符串
      if (typeof rawItemValue === 'string' && !isNaN(Number(rawItemValue))) {
        finalItemValue = Number(rawItemValue);
      } else if (typeof rawItemValue === 'number') {
        // 如果字典值是数字，保持不变，或者根据需要转换为字符串
        // finalItemValue = String(rawItemValue); // 如果希望 active/inactive-value 总是字符串
      }

      return {
        label: item.label || item.name,
        value: finalItemValue,
      };
    });

    dataLoaded.value = true;
    await nextTick();
  } catch (error) {
    console.error('Failed to fetch dictionary data:', error);
    options.value = [];
    dataLoaded.value = true;
  } finally {
    isLoading.value = false;
  }
};

// 监听 code 和 perms 变化，重新获取数据
watch([() => props.code, () => props.perms], fetchDictionaryData, {
  immediate: true,
});

const handleChange = (value) => {
  // el-switch 的 change 事件会发出 active-value 或 inactive-value
  // selectedValue 的 set 方法已经处理了 update:modelValue
  // 这里只需要额外 emit 组件自身的 change 事件
  emit('change', value);
};

// 暴露一些有用的方法和属性
defineExpose({
  options,
  isLoading,
  dataLoaded,
  refresh: fetchDictionaryData,
});
</script>

<style scoped>
/* Add any specific styles for RaDictSelect here if needed */
</style>
